﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TribesPSO
{
    /// <summary>
    /// EuclidianVectorBuilder is designed to create Euclidian Vectors without constructing an extra List of doubles.
    /// </summary>
    /// <remarks>
    /// Without the euclidian vector builder, if you wanted to do some math and create a Euclidian vector you would end
    /// up creating a list of doubles to hold the dimension values and then pass that into the EuclidianVector constructor.
    /// 
    /// Internally, the public EuclidianVector constructor would create another list of doubles to guarantee that it's immutable.
    /// 
    /// EuclidianVectorBuilder builds a list of doubles internally, but it won't let you change it after calling
    /// ToEuclidianVector.  This makes the underlying list de-facto immutable.
    /// This means that the EuclidianVector can make a shallow copy of EuclidianVectorBuilder's list without worrying
    /// about it changing later.
    /// </remarks>
    public sealed class EuclidianVectorBuilder
    {
        private List<double> dimensionData;
        private bool frozen;

        /// <summary>
        /// Gets the specified dimension data
        /// </summary>
        /// <param name="index">The dimension to get</param>
        /// <returns>The magnitude of the data in the specified dimension</returns>
        public double this[int index]
        {
            get
            {
                return dimensionData[index];
            }
        }

        /// <summary>
        /// Initializes a new EuclidianVectorBuilder object
        /// </summary>
        public EuclidianVectorBuilder()
        {
            dimensionData = new List<double>();
            frozen = false;
        }

        /// <summary>
        /// Adds a dimension of data to the EuclidianVectorBuilder
        /// </summary>
        /// <param name="data"></param>
        /// <exception cref="InvalidOperationException">Attempting to call AddDimensionData after a call to
        /// ToEuclidianVector() will raise an exception</exception>
        public void AddDimensionData(double data)
        {
            if (frozen) throw new InvalidOperationException("Can't add dimension data once the 'ToEuclidianVector()' method has been called");
            else dimensionData.Add(data);
        }

        /// <summary>
        /// Creates a EuclidianVector vector from the data provided through the AddDimensionData method.
        /// After calling ToEuclidianVector(), subsequent calls to AddDimensionData will throw an InvalidOperationException
        /// </summary>
        /// <returns></returns>
        public EuclidianVector ToEuclidianVector()
        {
            frozen = true;
            return EuclidianVector.EuclidianVectorFactory(dimensionData);
        }
    }
}
